/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonRequest;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonResponse;
import com.tencentcloudapi.iai.v20200303.models.PersonExDescriptionInfo;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.business.domain.sup.Gsgl;
import me.zhengjie.business.domain.sup.Rygl;
import me.zhengjie.business.repository.GsglRepository;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.exception.EntityExistException;
import me.zhengjie.business.repository.RyglRepository;
import me.zhengjie.business.service.RyglService;
import me.zhengjie.business.service.dto.RyglDto;
import me.zhengjie.business.service.dto.RyglQueryCriteria;
import me.zhengjie.business.service.mapstruct.RyglMapper;
import me.zhengjie.face.FaceUtil;
import me.zhengjie.face.config.FaceConfig;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.repository.LocalStorageRepository;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author xiahongbo
* @date 2022-04-11
**/
@Slf4j
@Service
@RequiredArgsConstructor
public class RyglServiceImpl implements RyglService {

    private final RyglRepository ryglRepository;
    private final RyglMapper ryglMapper;
    private final LocalStorageRepository localStorageRepository;
    private final GsglRepository gsglRepository;
    private final UserRepository userRepository;
    private final UserService userService;

    private final PasswordEncoder passwordEncoder;
    @Override
    public Map<String,Object> queryAll(RyglQueryCriteria criteria, Pageable pageable){
        Page<Rygl> page = ryglRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(ryglMapper::toDto));
    }

    @Override
    public List<RyglDto> queryAll(RyglQueryCriteria criteria){
        return ryglMapper.toDto(ryglRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public RyglDto findById(Long bisRyglId) {
        Rygl rygl = ryglRepository.findById(bisRyglId).orElseGet(Rygl::new);
        ValidationUtil.isNull(rygl.getBisRyglId(),"Rygl","bisRyglId",bisRyglId);
        return ryglMapper.toDto(rygl);
    }

    @Override
    public Rygl findByBisRyglUserId(Long userId) {
        return ryglRepository.findByBisRyglUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RyglDto create(Rygl resources) {
    /*    if(ryglRepository.findByBisRyglZjhm(resources.getBisRyglZjhm()) != null){
            throw new EntityExistException(Rygl.class,"BIS_RYGL_ZJHM",resources.getBisRyglZjhm());
        }*/
        Rygl isExist1 = ryglRepository.findByAndBisRyglLxdh(resources.getBisRyglLxdh());
        if(isExist1 != null) {
            throw new BadRequestException("手机号["+isExist1.getBisRyglLxdh()+"]已经存在");
        }
        Rygl isExist2 = ryglRepository.findByAndBisRyglZjhm(resources.getBisRyglZjhm());
        if(isExist2 != null) {
            throw new BadRequestException("身份证["+isExist2.getBisRyglZjhm()+"]已经存在");
        }
        Gsgl gsgl = gsglRepository.findByBisGsglId(resources.getGsgl().getBisGsglId());

        UserDetails userDetails = SecurityUtils.getCurrentUser();
        cn.hutool.json.JSONObject userJson = new cn.hutool.json.JSONObject(new cn.hutool.json.JSONObject(userDetails).get("user"));
        cn.hutool.json.JSONObject deptJson = new cn.hutool.json.JSONObject(userJson.get("dept"));
        String id = deptJson.getStr("id");

        // 新增商保公司，需要模拟用户插入
        User user = new User();
        user.setUsername(resources.getBisRyglLxdh());
        user.setPassword(passwordEncoder.encode(DefaultUtil.PASSWORD));
        user.setNickName(resources.getBisRyglXm());
        user.setPhone(resources.getBisRyglLxdh());
        user.setEnabled(true);
        user.setIsAdmin(false);


        // 新增用户，模拟护理公司部门
        Dept dept = new Dept();
        dept.setId(gsgl.getBisGsglUserId());
        user.setDept(dept);

        // 新增用户，模拟护理人员角色
        Set<Role> setRole = new HashSet<Role>();
        Role role = new Role();
        if("RYLX01".equals(resources.getBisRyglRylx())) {
            role.setId(DefaultUtil.ROLE_QYRY);
        } else if("RYLX02".equals(resources.getBisRyglRylx())) {
            role.setId(DefaultUtil.ROLE_PGRY);
        } else if("RYLX03".equals(resources.getBisRyglRylx())) {
            role.setId(DefaultUtil.ROLE_HLRY);
        } else if("RYLX04".equals(resources.getBisRyglRylx())) {
            role.setId(DefaultUtil.ROLE_SB);
        }
        setRole.add(role);
        user.setRoles(setRole);

        user = userRepository.save(user);

        resources.setGsgl(gsgl);
        resources.setBisRyglUserId(user.getId());

        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.setBisRyglId(snowflake.nextId());

        Rygl rygl = ryglRepository.save(resources);
        ryglRepository.updateByRyId(resources.getBisRyglRylx(), rygl.getBisRyglId());

        return ryglMapper.toDto(rygl);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Rygl resources) {
        Rygl rygl = ryglRepository.findById(resources.getBisRyglId()).orElseGet(Rygl::new);
        ValidationUtil.isNull( rygl.getBisRyglId(),"Rygl","id",resources.getBisRyglId());
        Rygl rygl1 = ryglRepository.findByBisRyglZjhm(resources.getBisRyglZjhm());
        if(rygl1 != null && !rygl1.getBisRyglId().equals(rygl.getBisRyglId())){
            throw new EntityExistException(Rygl.class,"BIS_RYGL_ZJHM",resources.getBisRyglZjhm());
        }

        rygl.copy(resources);
        ryglRepository.save(rygl);
        ryglRepository.updateByRyId(resources.getBisRyglRylx(), resources.getBisRyglId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(Long[] ids) {
        for (Long bisRyglId : ids) {
            Rygl rygl = ryglRepository.findById(bisRyglId).orElseGet(Rygl::new);
            Set<Long> userIds = new HashSet<>();
            userIds.add(rygl.getBisRyglUserId());
            userService.delete(userIds);
            ryglRepository.deleteById(bisRyglId);
        }
    }

    @Override
    public void download(List<RyglDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (RyglDto rygl : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("单位", rygl.getGsgl().getBisGsglQymc());
            map.put("姓名", rygl.getBisRyglXm());
            map.put("联系电话", rygl.getBisRyglLxdh());
            map.put("人员类型", rygl.getBisRyglRylx());
            map.put("性别", rygl.getBisRyglXb());
            map.put("身份证", rygl.getBisRyglZjhm());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void faceCreatePerson(Map<String, String> map) {
        log.info("[RyglServiceImpl - faceCreatePerson]--------------- 上传员工头像 start" );
        log.info("[RyglServiceImpl - faceCreatePerson]--------------- 人员信息 ：{} ", map);
        try{

            String xm = map.get("xm");
            String sfz = map.get("sfz");
            String lxdh = map.get("lxdh");
            String userId = map.get("userId");
            Long xb = Long.parseLong(map.get("xb"));
            String ddbm = map.get("ddbm");
            String ddmc = map.get("ddmc");
            String fileIds = map.get("fileIds");

            String imageUrl = "";

            // 3.上传图片 关联签约id
            if(fileIds != null && !fileIds.equals("")){
                String[] picIds = fileIds.split(",");
                if(picIds.length == 1) {
                    Long storage_id = Long.parseLong(picIds[0]);
                    LocalStorage localStorage = localStorageRepository.findById(storage_id).orElseGet(LocalStorage::new);
                    imageUrl = localStorage.getPath();
                    localStorage.setYwid(userId);

                    log.info("[RyglServiceImpl - faceCreatePerson]--------------- 查询头像附件地址 :{} ", imageUrl);


                    String PersonName = "["+ddbm+"]"+xm;

                    JSONObject userJson = new JSONObject();
                    userJson.put("GroupId", "NurseList");
                    userJson.put("PersonName", PersonName);
                    userJson.put("PersonId", userId);
                    userJson.put("Gender", xb);
                    userJson.put("Url", imageUrl);
                    userJson.put("UniquePersonControl", 2);
                    userJson.put("QualityControl", 2);
                    userJson.put("NeedRotateDetection", 0);

                    JSONArray paramsArray = new JSONArray();
                    JSONObject params0 = new JSONObject();
                    params0.put("PersonExDescriptionIndex", 0);
                    params0.put("PersonExDescription", ddbm);
                    JSONObject params1 = new JSONObject();
                    params1.put("PersonExDescriptionIndex", 1);
                    params1.put("PersonExDescription", ddmc);
                    JSONObject params2 = new JSONObject();
                    params2.put("PersonExDescriptionIndex", 2);
                    params2.put("PersonExDescription", xm);
                    JSONObject params3 = new JSONObject();
                    params3.put("PersonExDescriptionIndex", 3);
                    params3.put("PersonExDescription", sfz);
                    JSONObject params4 = new JSONObject();
                    params4.put("PersonExDescriptionIndex", 4);
                    params4.put("PersonExDescription", lxdh);
                    paramsArray.add(params0);
                    paramsArray.add(params1);
                    paramsArray.add(params2);
                    paramsArray.add(params3);
                    paramsArray.add(params4);

                    userJson.put("PersonExDescriptionInfos", paramsArray);

                    String action = "CreatePerson";
                    log.info("[RyglServiceImpl - faceCreatePerson]--------------- 连接人脸识别服务 ");
                    String resp = FaceUtil.doRequest(FaceConfig.secretId, FaceConfig.secretKey, action, userJson.toString(), FaceConfig.apiUrl);
                    log.info("[RyglServiceImpl - faceCreatePerson]--------------- 腾讯云人脸识别返回结果：{}", resp);
                    log.info("[RyglServiceImpl - faceCreatePerson]--------------- 连接人脸识别服务成功 ");
                    // 返回的resp是一个CreatePersonResponse的实例，与请求对象对应
                    JSONObject respJson = JSONObject.parseObject(resp).getJSONObject("Response");
                    // 输出json格式的字符串回包
                    String faceId = respJson.containsKey("FaceId") ? respJson.getString("FaceId") : "";
                    String SimilarPersonId = respJson.containsKey("SimilarPersonId") ? respJson.getString("SimilarPersonId") : "";
                    String errorMsg = respJson.containsKey("Error") ? respJson.getJSONObject("Error").getString("Message") : "";
                    if(StringUtils.isEmpty(errorMsg)) {
                        if(StringUtils.isEmpty(faceId) && StringUtils.isNotEmpty(SimilarPersonId)) {
                            Rygl rygl = this.findByBisRyglUserId(Long.parseLong(SimilarPersonId));
                            log.info("[RyglServiceImpl - faceCreatePerson]--------------- 头像疑似重复：{}", rygl.getBisRyglXm());
                            throw new BadRequestException("此头像疑似和"+rygl.getBisRyglXm()+"重复");
                        } else {
                            log.info("[RyglServiceImpl - faceCreatePerson]--------------- 关联附件 ");
                            localStorageRepository.save(localStorage);
                        }
                    } else {
                        log.info("[RyglServiceImpl - faceCreatePerson]--------------- 报错：{}", errorMsg);
                        throw new BadRequestException(errorMsg);
                    }
                } else {
                    throw new BadRequestException("请上传一个头像");
                }
            } else {
                throw new BadRequestException("未上传头像");
            }
        }catch (NoSuchAlgorithmException e) {
            log.info("[RyglServiceImpl - faceCreatePerson]--------------- 上传员工头像：{}", e.getMessage());
            throw new BadRequestException(e.toString());
        } catch (IOException e) {
            log.info("[RyglServiceImpl - faceCreatePerson]--------------- 上传员工头像：{}", e.getMessage());
            throw new BadRequestException(e.toString());
        } catch (InvalidKeyException e) {
            log.info("[RyglServiceImpl - faceCreatePerson]--------------- 上传员工头像：{}", e.getMessage());
            throw new BadRequestException(e.toString());
        }
        log.info("[RyglServiceImpl - faceCreatePerson]--------------- 上传员工头像 end");
    }
}
